package com.beiji.lib.pen

import android.app.Application
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Handler
import android.os.Looper
import android.widget.Toast
import com.beiji.lib.pen.constants.PenType
import com.beiji.lib.pen.model.PenInfo
import com.tqltech.tqlpencomm.BLEException
import com.tqltech.tqlpencomm.BLEScanner
import com.tqltech.tqlpencomm.PenCommAgent

/**
 * 蓝牙笔扫描器
 * 腾千里SDK的connect方法里有做限制，必须使用SDK的搜索逻辑，所以这里做一层封装，方便自定义
 * Created by X on 2018/7/23.
 */
class PenScanner {
    companion object {
        private val TAG = PenScanner::class.java.simpleName
        val instance = PenScanner()

        /**
         * 以下是腾千里SDK的init方法的两个返回值
         */
        private const val ERROR_BLUETOOTH_NOT_SUPPORT = 30001
        private const val ERROR_BLE_NOT_SUPPORT = 30002

        private const val ERROR_UNKNOWN = -1
    }

    private val handler = Handler(Looper.getMainLooper())

    private var penCommAgent: PenCommAgent? = null
    private var bluetoothAdapter: BluetoothAdapter? = null
    private var scanPenCallBack: ScanPenCallBack? = null
    private var application: Application? = null

    fun init(application: Application) {
        this.application = application
        penCommAgent = PenCommAgent.GetInstance(application)
    }

    private val onBLEScanListener = object : BLEScanner.OnBLEScanListener {
        override fun onScanFailed(p0: BLEException?) {}

        override fun onScanResult(device: BluetoothDevice?, p1: Int, p2: ByteArray?) {
            device?.let {
                if (it.isPen()) {
                    PenLog.i(TAG, "pen found -> $it")
                    val pen = PenInfo(generatePenName(it.address), it.address, PenType.UNKNOWN)
                    scanPenCallBack?.onPenFound(pen)
                }
            }
        }

    }

    private val receiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            val action = intent.action
            when (action) {
                BluetoothAdapter.ACTION_STATE_CHANGED -> {
                    val state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF)
                    when (state) {
                        BluetoothAdapter.STATE_OFF -> {
                            PenLog.d(TAG, "Bluetooth state -> OFF")
                        }

                        BluetoothAdapter.STATE_TURNING_ON -> {
                            PenLog.d(TAG, "Bluetooth state -> TURNING_ON")
                        }

                        BluetoothAdapter.STATE_ON -> {
                            PenLog.d(TAG, "Bluetooth state -> ON")
                            doScan()
                        }

                        BluetoothAdapter.STATE_TURNING_OFF -> {
                            PenLog.d(TAG, "Bluetooth state -> TURNING_OFF")
                        }
                    }
                }
            }
        }
    }

    /**
     * 辨别是否蓝牙笔
     *
     */
    fun BluetoothDevice.isPen(): Boolean {
//        return (name != null && name.contains("smartpen", true))
        return true
    }

    private fun generatePenName(macAddress: String): String {
        val length = macAddress.length
        var suffix = if (length <= 5) macAddress else macAddress.substring(length - 5, length)
        suffix = suffix.replace(":", "")
        return "TechPage+$suffix"
    }

    /**
     * 开始扫描
     * @param timeout 默认值为0，无超时，单位为s
     */
    fun startScan(scanPenCallBack: ScanPenCallBack, timeout: Int = 0): Boolean {

        val intentFilter = IntentFilter()
        intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED)
        application?.registerReceiver(receiver, intentFilter)


        PenLog.e(TAG, "start scan")
        handler.removeCallbacksAndMessages(null)
        this.scanPenCallBack = scanPenCallBack
        val initResult = penCommAgent?.init() ?: -1
        when (initResult) {
            ERROR_BLUETOOTH_NOT_SUPPORT -> {
                Toast.makeText(application, "该设备不支持蓝牙", Toast.LENGTH_SHORT).show()
                return false
            }
            ERROR_BLE_NOT_SUPPORT -> {
                Toast.makeText(application, "该设备不支持BLE", Toast.LENGTH_SHORT).show()
                return false
            }
            ERROR_UNKNOWN -> {
                return false
            }
        }
        //FindAllDevices方法的默认超时逻辑有问题，在stopScan的时候没有把timeoutHandler里的message清空，
        // 导致即便已经stopScan了，还是会收到之前的超时回调（如果多次startScan更是会收到多个）
        doScan()
        //超时
//        if (timeout > 0) {
//            handler.postDelayed({
//                PenLog.e(TAG, "scan timeout.")
//                scanPenCallBack.onTimeOut()
//                stopScan()
//            }, timeout * 1000L
//            )
//        }
        return true
    }

    private fun doScan() {
        val adapter = getBluetoothAdapter(application) ?: return
        if (!adapter.isEnabled) {
            PenLog.e(TAG, "bluetooth is closed.starting...")
            adapter.enable()
            //蓝牙开启需要时间，等收到蓝牙开启的广播再搜索笔
            return
        }
        penCommAgent?.FindAllDevices(onBLEScanListener);
//        penCommAgent?.FindAllDevices(1000, onBLEScanListener)
    }

    private fun doStopScan() {
        val adapter = getBluetoothAdapter(application)
        if (adapter == null || !adapter.isEnabled) {
            return
        }
        penCommAgent?.stopFindAllDevices()
    }

    /**
     * 停止扫描
     */
    fun stopScan() {
        PenLog.e(TAG, "stop scan")
        if (scanPenCallBack == null){
            return
        }
        doStopScan()
        try {
            application?.unregisterReceiver(receiver)
        } catch (e: Exception) {
        }
        scanPenCallBack = null
        handler.removeCallbacksAndMessages(null)
    }

    interface ScanPenCallBack {
        fun onPenFound(pen: PenInfo)
        fun onTimeOut()
    }

    private fun getBluetoothAdapter(context: Context?): BluetoothAdapter? {
        if (bluetoothAdapter != null) {
            return bluetoothAdapter
        }
        context ?: return null
        return if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
            val bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
            bluetoothManager.adapter
        } else {
            BluetoothAdapter.getDefaultAdapter()
        }
    }


}